let childProcess = require("child_process");
let http = require("http");
let path = require("path");
const TOOLS = require(path.join(__dirname, '/tools.js'));

let appLoop = [];
let cp = {};
let responseHost = undefined;
let responsePort = undefined;
let responsePath = undefined;
let forkChildProcess = (hash, deployList) => {
  try {
    cp[hash] = { cp: null, finished: [], deployList };
    cp[hash].cp = childProcess.fork(path.join(__dirname, '/work.js'));
    cp[hash].cp.on("message", (m) => {
      cp[m.hash].finished.push(m.data);
      appLoop.splice(appLoop.indexOf(m.data.appid), 1);
      if (m.data.appid === cp[m.hash].deployList[cp[m.hash].deployList.length - 1].appid) {
        response({type: 'end', hash: m.hash, data: cp[m.hash].finished})
        cp[hash].cp.send({ exit: true });
        let clock = setTimeout(() => {
          delete cp[m.hash];
          clearTimeout(clock);
        }, 60000);
      } else {
        response({type: 'ing', hash: m.hash, data: cp[m.hash].finished})
      }
    });
    cp[hash].cp.send({ hash, deployList });
  } catch (error) {
    console.log(error)
    response({code: -1, message: error})
  }

};

let router = async (req, res, hash) => {
  try {
    let route = req.url;
    let method = req.method;
  
    if (route === "/postdata" && method === "POST") {
      let { response, deployList } = await ((require) => {
        return new Promise((resolve, reject) => {
          let postData = "";
          require.on("data", (chunk) => {
            postData += chunk;
          });
          require.on("end", () => {
            console.log(postData, 'postData')
            postData = JSON.parse(postData);
            resolve(postData);
          });
        });
      })(req);
      responseHost = response.host;
      responsePort = response.port;
      responsePath = response.path;
      let packageMsg = TOOLS.getPackageSize(deployList[0].project);
      let isPass = TOOLS.checkPackageSize(packageMsg.countSize, packageMsg.subPackages);
      if (!isPass.isPass) {
        res.end(JSON.stringify({ code: -1, message: isPass, data: null }));
        return;
      }
      deployList.forEach((item) => {
        if (appLoop.indexOf(item.appid) != -1) {
          res.end(JSON.stringify({ code: -1, message: `${item.appid}已在发布任务队列，请稍后再试。`, data: null }));
          return;
        }
      });
      deployList.forEach((item) => {
        appLoop.push(item.appid);
      });
      res.end(JSON.stringify({ code: 0, message: `提交成功，发布任务开始！`, data: null }));
      forkChildProcess(hash, deployList);
    } else if (route === "/result" && method === "GET") {
      if (!cp.hasOwnProperty(hash)) {
        res.end(JSON.stringify({ code: -1, message: "请先提交发布数据", data: null }));
      } else {
        if (cp[hash].finished.length < cp[hash].deployList.length) {
          res.end(JSON.stringify({ status: "success", type: "ing", data: cp[hash].finished }));
        } else {
          res.end(JSON.stringify({ status: "success", type: "end", data: cp[hash].finished }));
        }
      }
    } else {
      res.end(JSON.stringify({ code: -1, message: "路径不存在", data: null }));
    }
  } catch (error) {
    console.log(error)
    res.end(JSON.stringify({ code: -1, message: error, data: null }));
  }

};

function response(data) {
  try {
    if (responseHost && responsePort && responsePath) {
      data = JSON.stringify(data);
      let opt = {
        host: responseHost,
        port: responsePort,
        method: "POST",
        path: responsePath,
        headers: {
          "Content-Type": "application/json",
          "Content-Length": data.length,
        }
      };
    
      let body = "";
      let req = http.request(opt, function (res) {
          res.on("data", function (data) {
              body += data;
            })
            .on("end", function () {
              console.count(data['m-hash'])
            });
        })
        .on("error", function (e) {
          console.log("error: " + e.message);
        });
      req.write(data)
      req.end()
    } else {
      console.log("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
      console.log(`Error: Incomplete interface parameters`);
      console.log("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    }
  } catch (error) {
    console.log("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    console.log(`Error: ${error}`);
    console.log("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
  }

}

let httpServer = async (port) => {
  let server = http.createServer();
  server.on("request", async (req, res) => {
    res.setHeader("Access-Control-Allow-Origin", "*");
    res.setHeader("Content-Type", "application/json");
    res.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
    if (req.headers.hasOwnProperty("m-hash")) {
      if (req.headers["m-hash"].constructor !== String) {
        res.end(JSON.stringify({ status: "error", data: "请求头m-hash不合法，必须为字符串类型" }));
        return;
      }
    } else {
      res.end(JSON.stringify({ status: "error", data: "缺少请求头m-hash" }));
      return;
    }
    router(req, res, req.headers["m-hash"]);
  });

  server.listen(port, () => {
    console.log("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    console.log(`Service started`);
    console.log("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
  });
};

module.exports = server = port => {
  httpServer(port);
};
